package com.vkdasari.youtube.upload;

import java.awt.GridLayout;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

import javax.activation.MimetypesFileTypeMap;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import org.apache.log4j.Logger;

import com.google.gdata.client.media.ResumableGDataFileUploader;
import com.google.gdata.client.uploader.ProgressListener;
import com.google.gdata.client.uploader.ResumableHttpFileUploader;
import com.google.gdata.client.youtube.YouTubeService;
import com.google.gdata.data.media.MediaFileSource;
import com.google.gdata.data.media.mediarss.MediaCategory;
import com.google.gdata.data.media.mediarss.MediaDescription;
import com.google.gdata.data.media.mediarss.MediaKeywords;
import com.google.gdata.data.media.mediarss.MediaTitle;
import com.google.gdata.data.youtube.VideoEntry;
import com.google.gdata.data.youtube.YouTubeMediaGroup;
import com.google.gdata.data.youtube.YouTubeNamespace;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;
import com.vkdasari.youtube.model.Video;
import com.vkdasari.youtube.ui.MainPanel;
import com.vkdasari.youtube.ui.model.VideoUploadTableModel;

public class YouTubeUploader {

	/**
	 * The URL used to resumable upload
	 */
	public static final String RESUMABLE_UPLOAD_URL = "http://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads";

	/** Time interval at which upload task will notify about the progress */
	private static final int PROGRESS_UPDATE_INTERVAL = 1000;

	/** Max size for each upload chunk */
	private static final int DEFAULT_CHUNK_SIZE = 10000000;
	
	private static final Logger log = Logger.getLogger(YouTubeUploader.class);
	
	private String sourceFolder;
	
	private int currentFile = 0;
	
	VideoUploadTableModel tableModel;
	
	private static YouTubeUploader instance = null;
	
	/**
	 * @return the sourceFolder
	 */
	public String getSourceFolder() {
		return sourceFolder;
	}

	/**
	 * @param sourceFolder the sourceFolder to set
	 */
	public void setSourceFolder(String sourceFolder) {
		this.sourceFolder = sourceFolder;
	}

	/**
	 * Input stream for reading user input.
	 */
	private static final BufferedReader bufferedReader = new BufferedReader(
			new InputStreamReader(System.in));

	/**
	 * A {@link ProgressListener} implementation to track upload progress. The
	 * listener can track multiple uploads at the same time.
	 */
	private class FileUploadProgressListener implements ProgressListener {
		public synchronized void progressChanged(
				ResumableHttpFileUploader uploader) {
			switch (uploader.getUploadState()) {
			case COMPLETE:
				log.info("Upload Completed");
				break;
			case CLIENT_ERROR:
				log.info("Upload Failed");
				break;
			case IN_PROGRESS:
				log.info(String.format("%3.0f",
						uploader.getProgress() * 100)
						+ "%");
				break;
			case NOT_STARTED:
				log.info("Upload Not Started");
				break;
			}
		}
	}
	
	public static YouTubeUploader getInstance(){
		if(null == instance){
			instance = new YouTubeUploader();
		}
		return instance;
	}

	private YouTubeUploader() {

		tableModel = MainPanel.getInstance().getUploadsTableModel();


		try {
			uploadAll(YouTubeSessionHandler.getInstance().getService());

		} catch (IOException e) {
			// Communications error
			System.err
					.println("There was a problem communicating with the service.");
			e.printStackTrace();
		} catch (ServiceException se) {
			System.out.println("Sorry, your upload was invalid:");
			System.out.println(se.getResponseBody());
			se.printStackTrace();
		} catch (InterruptedException ie) {
			System.out.println("Upload interrupted");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}

	private void uploadAll(YouTubeService service) throws Exception {
		
		Video[] videos = tableModel.getVideos();
		int i=0;
		for(Video video : videos){
			uploadVideo(service, new File(video.getFilelocation()), i);
			i++;
		}
	}

	/**
	 * Uploads a new video to YouTube.
	 * 
	 * @param service
	 *            An authenticated YouTubeService object.
	 * @throws IOException
	 *             Problems reading user input.
	 */
	private void uploadVideo(YouTubeService service, File fileToUpload, int location)
			throws IOException, ServiceException, InterruptedException {

		tableModel.setValueAt("Uploading..", currentFile, 6);
		File videoFile = fileToUpload;
		if (!videoFile.exists()) {
			log.info("Sorry, that video doesn't exist.");
			return;
		}
		System.out.println("Starting Upload.. "
				+ fileToUpload.getAbsolutePath());

		MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();

		// only by file name
		String mimeType = mimeTypesMap.getContentType(videoFile);

		// or by actual File instance
		if (null == mimeType || mimeType.length() < 0) {
			mimeType = mimeTypesMap.getContentType(videoFile);
		}

		MediaFileSource ms = new MediaFileSource(videoFile, mimeType);

		String videoTitle = videoFile.getName();

		VideoEntry newEntry = new VideoEntry();
		YouTubeMediaGroup mg = newEntry.getOrCreateMediaGroup();
		mg.addCategory(new MediaCategory(YouTubeNamespace.CATEGORY_SCHEME,
				"Tech"));
		mg.setTitle(new MediaTitle());
		mg.getTitle().setPlainTextContent(videoTitle);
		mg.setKeywords(new MediaKeywords());
		mg.getKeywords().addKeyword("vijay");
		mg.setDescription(new MediaDescription());
		mg.getDescription().setPlainTextContent(videoTitle);
		mg.setPrivate(true);

		FileUploadProgressListener listener = new FileUploadProgressListener();
		ResumableGDataFileUploader uploader = new ResumableGDataFileUploader.Builder(
				service, new URL(RESUMABLE_UPLOAD_URL), ms, newEntry).title(
				videoTitle).trackProgress(listener, PROGRESS_UPDATE_INTERVAL)
				.chunkSize(DEFAULT_CHUNK_SIZE).build();

		uploader.start();
		while (!uploader.isDone()) {
			Thread.sleep(PROGRESS_UPDATE_INTERVAL);
		}

		String status = "";
		switch (uploader.getUploadState()) {
		case COMPLETE:
			status = "Uploaded successfully";
			log.info(status);
			break;
		case CLIENT_ERROR:
			status = "Upload Failed";
			log.info(status);
			break;
		default:
			status = "Unexpected upload status";
			log.info(status);
			break;
		}
		
		tableModel.setValueAt(status, currentFile, 6);
		currentFile++;
		
	}



}
